#include "define.h"
#include "taskDrvRS.h"
#include <string.h>
#include <stdio.h>

/* Callback function dedicated to printf output interface */
//int _user_putc (char c);

/**********************************************************************
 * Definition dedicated to the local functions.
 **********************************************************************/
EventMaskType   RS_event;

//RS_message_tRef	RS_list_head;			//	Start of message queue
//RS_message_tRef	RS_current_message;		//	Current message
//unsigned char	RS_list_count = 0;		//	Number of items currently in queue

//RS_message_tRef	RS_list_head_rcv;		//	Start of message queue
//unsigned char	RS_list_count_rcv = 0;	//	Number of items currently in queue

//unsigned int    TX_ByteNumber = 0;
//unsigned int    RX_ByteNumber = 0;

char commande;

/**********************************************************************
 * ----------------- RS DRIVER - PIC18 USART MANAGEMENT ---------------
 *
 * void
 *
 **********************************************************************/


TASK(taskRS232Drv)
{  
	/*  
	// Reset USART registers to POR state
	TXSTA            = 0; 
	RCSTA            = 0;
	
	// Change baud rate here  [cf datasheet]
	// SPBRG = 255; for   9600 [40MHZ only]
	// SPBRG =  21; for 115200 [40MHZ only]
	SPBRG            = 21;
	TXSTAbits.BRGH   = 1;
	
	TXSTAbits.SYNC   = 0;
	RCSTAbits.SPEN   = 1;
	TXSTAbits.TXEN   = 0;
	RCSTAbits.CREN   = 1;
	TRISCbits.TRISC7 = 1;
	TRISCbits.TRISC6 = 0;
	
	PIR1bits.TXIF    = 0;
	PIR1bits.RCIF    = 0;
	PIE1bits.RCIE    = 1;
	PIE1bits.TXIE    = 0;  
	RS_current_message = NULL;
	
	// for 'printf' function redirection 
	stdout = _H_USER;
	*/
	
	InitRS232();

	while(1)
	{
		WaitEvent(RS_NEW_MSG | RS_RCV_MSG);
		GetEvent(ID_TASK_RS232DRV, &RS_event);
		
		if (RS_event & RS_RCV_MSG)
		{
			ClearEvent(RS_RCV_MSG);
			traiteCommande(commande);
		}
		if (RS_event & RS_NEW_MSG)
		{
		  	ClearEvent(RS_NEW_MSG);
/*		  	if (PIE1bits.TXIE == 0)
		  	{
		    	if (RS_current_message != NULL)
		    	{
		      		RS_current_message->length = 0;
		      		SetEvent(RS_current_message->CallerID, RS_QUEUE_EMPTY);
		    	}
		    	RS_current_message = RS_deqMsg();
		    	if (RS_current_message != NULL)
		    	{
			      	TX_ByteNumber = 0;
			      	TXREG = RS_current_message->data[0];
			      	TXSTAbits.TXEN = 1;
			      	PIE1bits.TXIE = 1;
			    }
			}
*/
		}

	}
}


/****************************************************************************/
/* 									Traite Commande							*/
/****************************************************************************/

void traiteCommande(char c)
{
	switch(c)
	{
		case CMD_CONNECT:
			putc(CMD_CONNECT+1,_H_USART);
			putc(CMD_ACK,_H_USART);
			break;
		default:
			putc(c,_H_USART);
			putc(CMD_NACK,_H_USART);
			break;
	}

}

/****************************************************************************/
/* 									Init RS232							*/
/****************************************************************************/

void InitRS232()
{

/* Reset USART registers to POR state */
  	TXSTA            = 0; 
	RCSTA            = 0;

//set up les ports TX et RX
//la logique dirait  1 et 0 mais la datasheet dit  1 et 1
	TRISCbits.TRISC7 = 1;
	TRISCbits.TRISC6 = 0;
  
/*
To set up an Asynchronous Transmission:
1. Initialize the SPBRGH:SPBRG registers for the
appropriate baud rate. Set or clear the BRGH
and BRG16 bits, as required, to achieve the
desired baud rate.
*/
	//set the baud rate to 40000000/( 64*X ) - 1
	SPBRGH=0;
	SPBRG=64; //= X , 64 -> 9600

//	SPBRGH=32;//b100000
//	SPBRG=140; //0.3K //b10001100
//	SPBRG=8332;

	
	//multiplie par 64 et utilise 8 bits (cf formule d'avant)
	BAUDCON = 0;
	TXSTAbits.BRGH=0; 
/*
2. Enable the asynchronous serial port by clearing
bit SYNC and setting bit SPEN.
*/

	TXSTAbits.SYNC=0;						//asynchronous
	RCSTAbits.SPEN=1;						//enable serial port pins

/*
3. If interrupts are desired, set enable bit TXIE.
*/
	PIR1bits.RCIF = 0;	//disable the PIR1bits.RCIF bit being set
	PIE1bits.TXIE=0;	// disable trasmition interruption
	PIE1bits.RCIE=1; 	// enable receive interruption

/*
4. If 9-bit transmission is desired, set transmit bit
TX9. Can be used as address/data bit.
*/

	TXSTAbits.TX9 = 0;						//9-bit transmission -> 1 sinon 0 =8 bits
	RCSTAbits.RX9 = 0;						//8-bit reception

/*
5. Enable the transmission by setting bit TXEN
which will also set bit TXIF.*/

	TXSTAbits.TXEN=1;
	RCSTAbits.CREN=1;

/*
8. If using interrupts, ensure that the GIE and PEIE
bits in the INTCON register (INTCON<7:6>) are
set.
*/

	INTCONbits.GIE=1;
	INTCONbits.PEIE=1;

} // fin InitRS232()

/**********************************************************************
 *	Enqueue a client packet object into the RS task queue.
 *
 *	Once placed in queue, client must not modify the data
 *	otherwise unpredictable results. To safely change the object,
 *	dequeue, modify, re-enqueue.
 *
 *  The code in mainly executed in critical region [SuspendAllInterrupt]
 *  because many tasks can call this function at the same time and break
 *  the FIFO list.
 *
 * @param  toEnqueue  IN  New message structure reference
 * @param  data       IN  Buffer which contains the string of data
 * @param  length     IN  Length of the Buffer field
 * @return Status         E_OK if toEnqueue is well attached to the list
 *                        E_OS_STATE if message could not be enqueued
 **********************************************************************/
/*
StatusType RS_enqMsg(RS_message_tRef toEnqueue, unsigned char *data, unsigned int length)
{
  RS_message_tRef RS_list_itor;

  if (toEnqueue != NULL)
  {
    SuspendOSInterrupts();
    if (RS_list_head == NULL)
      RS_list_head = toEnqueue;
    else
    {
      RS_list_itor = RS_list_head;
      while (RS_list_itor->next != NULL)
        RS_list_itor = RS_list_itor->next;
      RS_list_itor->next = toEnqueue;
    }
    toEnqueue->next     = NULL;
    toEnqueue->CallerID = id_tsk_run;
    toEnqueue->length   = length;
    toEnqueue->data     = data;
    RS_list_count++;
    ResumeOSInterrupts();
    return E_OK;
  }
  else
    return E_OS_STATE;
}
*/
/**********************************************************************
 *	Dequeue a client message from the RS task queue.
 *
 * @param  void
 * @return RS_list_itor   Reference of the top of the FIFO list
 *                        (next enqueued message)
 *********************************************************************/
/*
RS_message_tRef RS_deqMsg(void)
{
  RS_message_tRef RS_list_itor;

  RS_list_itor = NULL;
  if (RS_list_head != NULL)
  {
    RS_list_itor = RS_list_head;
    RS_list_head = RS_list_head->next;
    RS_list_count--;
  }
  return RS_list_itor;
} 
*/
/**********************************************************************
 *	Enqueue a client packet object into the RS task queue.
 *
 *	Once placed in queue, client must not modify the data
 *	otherwise unpredictable results. To safely change the object,
 *	dequeue, modify, re-enqueue.
 *
 *  The code in mainly executed in critical region [SuspendAllInterrupt]
 *  because many tasks can call this function at the same time and break
 *  the FIFO list.
 *
 * @param  toEnqueue  IN  New message structure reference
 * @return Status         E_OK if toEnqueue is well attached to the list
 *                        E_OS_STATE if message could not be enqueued
 **********************************************************************/
/*
StatusType RS_RCV_Register(RS_message_tRef toEnqueue, unsigned char *data,unsigned int length)
{
  RS_message_tRef RS_list_itor;

  if (toEnqueue != NULL)
  {
    SuspendOSInterrupts();
    if (RS_list_head_rcv == NULL)
      RS_list_head_rcv = toEnqueue;
    else
    {
      RS_list_itor = RS_list_head_rcv;
      while (RS_list_itor->next != NULL)
        RS_list_itor = RS_list_itor->next;
      RS_list_itor->next = toEnqueue;
    }
    toEnqueue->next     = NULL;
    toEnqueue->CallerID = id_tsk_run;
    toEnqueue->length   = length;
    toEnqueue->data     = data;
    RS_list_count_rcv++;
    ResumeOSInterrupts();
    return E_OK;
  }
  else
    return E_OS_STATE;
}
*/
/**********************************************************************
 *	Fill the structure with the printf content.
 *
 *  The code in mainly executed in critical region [SuspendAllInterrupt]
 *  because many tasks can call this function at the same time and break
 *  the FIFO list.
 *
 * @param  c          IN  Next character coming from the printf function
 * @return ByteNumber     Current char index in the buffer
 *********************************************************************/
/*
int _user_putc (char c)
{
  RS_message_tRef RS_list_itor;

  SuspendOSInterrupts();
  RS_list_itor = RS_list_head;
  while (RS_list_itor->CallerID != id_tsk_run)
  {
    if (RS_list_itor->next == NULL)
      return 0;
    RS_list_itor = RS_list_itor->next;
  }
  RS_list_itor->data[RS_list_itor->length] = c;
  RS_list_itor->length++;
  ResumeOSInterrupts();
  return RS_list_itor->length;
}
*/

/*
int putchar(char c)
{
	if(!TXSTAbits.TXEN) // if not enable
		return -1;
	while(!TXSTAbits.TRMT);	// wait to be empty
	TXREG = c;

	return (int)c;
}
*/
/**********************************************************************
 * Part of the transmiter interrupt.
 *
 * @param  void
 * @return void 
 **********************************************************************/
/*
void RS_TX_INT(void)
{   
	if ((TX_ByteNumber >= 0) && (TX_ByteNumber < RS_current_message->length))
	{
		TXREG = RS_current_message->data[TX_ByteNumber];
	}
	if (TX_ByteNumber  == (RS_current_message->length))
	{
	  	PIE1bits.TXIE = 0;
	  	SetEvent(ID_TASK_RS232DRV, RS_NEW_MSG);
	  	TX_ByteNumber = -1;
	}
	
	TX_ByteNumber++;
	return;
}
*/
/**********************************************************************
 * Part of the recepteur interrupt.
 *
 * @param  void
 * @return void 
 **********************************************************************/
void RS_RX_INT(void)
{
  	/*
	PIR1bits.RCIF = 0;
  	if ((RX_ByteNumber >= 0) && (RX_ByteNumber < RS_list_head_rcv->length))
		RS_list_head_rcv->data[RX_ByteNumber] = RCREG;
  	if (RX_ByteNumber == (RS_list_head_rcv->length))
  	{
    	SetEvent(RS_list_head_rcv->CallerID, RS_QUEUE_FULL);
    	RX_ByteNumber = -1;
  	}
  	RX_ByteNumber++;
  	return;
	*/
	PIR1bits.RCIF = 0;
	commande = RCREG;
	SetEvent(ID_TASK_RS232DRV,RS_RCV_MSG);
	
	return;
}

/* End of file : drv_rs.c */
